# -*- coding: utf-8 -*-
import socket
import sys
if sys.version > '3':
    import queue as Queue
else:
    import Queue

'''
控制器接收交换机信息模块
'''


class TopoServer():
    def __init__(self, listen_port, aim_port=None):
        '''
        :param listen_port: 监听端口
        '''
        self.listen_port = listen_port
        self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.s.bind(('0.0.0.0', self.listen_port))
        self.IP_map = {}  # 交换机连接到控制器的IP与其Ad_Hoc网络中的IP的对应关系,k为Ad_Hoc网络IP
        self.IP_map_R = {}  # 交换机连接到控制器的IP与其Ad_Hoc网络中的IP的对应关系,k为连接到控制器的网络IP
        # self.switch_mac = []  # 交换机Ad_Hoc网络IP与mac
        self.switch_mac = {}  # 交换机Ad_Hoc网络IP与mac的字典，键IP，值mac
        self.switch_addr = []  # 存储所已连接交换机地址
        self.link_msg_queue = Queue.Queue()  # 链路更新队列，用于向控制器传递消息

    def recv_loop(self):
        '''
        接收链路状态
        :return:
        '''
        while True:
            data, addr = self.s.recvfrom(1024)
            msg = data.decode('utf-8').split()
            # print('recv msg %s'%msg)
            if msg[2] == '2':  # 新的交换机
                self.process_new_switch(addr, msg)
                continue
            # yield msg # yield循环中，所有变量都只能是局部变量，否则会报错，改用队列
            self.link_msg_queue.put(msg)

    def process_new_switch(self, new_addr, msg):
        '''
        处理新的交换机连接
        '''
        self.s.sendto(b'1', new_addr)  # 随便回复一个信息表示收到
        for addr in self.switch_addr:  # 向其他用户广播这个新用户的mac
            data = ('%s %s' % (msg[0], msg[1])).encode('utf-8')
            self.s.sendto(data, addr)
        for IP, mac in self.switch_mac.items():  # 向这个用户发送其他所有节点的IP与mac
            data = ('%s %s' % (IP, mac)).encode('utf-8')
            self.s.sendto(data, new_addr)
        # 把新用户更新到表中
        self.IP_map[msg[0]] = new_addr[0]
        self.IP_map_R[new_addr[0]] = msg[0]
        # self.switch_mac.append((msg[0], msg[1]))
        self.switch_mac[msg[0]] = msg[1]
        self.switch_addr.append(new_addr)


# if __name__ == '__main__':
#     ts = TopoServer(6699)
#     rl = ts.recv_loop()
#     while True:
#         print(next(rl))
